package com.example.onlinemonitoring.Util.tem;

import com.example.onlinemonitoring.Util.ConditionDispose;
import com.example.onlinemonitoring.Util.DefaultProperty;
import com.example.onlinemonitoring.Util.DefaultPropertyByInsert;
import com.example.onlinemonitoring.Util.HexUtil;
import com.example.onlinemonitoring.model.Appalarm;
import com.example.onlinemonitoring.model.Dlzllconfig;
import com.example.onlinemonitoring.model.common.MyResult;
import com.example.onlinemonitoring.model.common.pagebase;
import com.example.onlinemonitoring.query.QueryObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.ibatis.session.RowBounds;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import tk.mybatis.mapper.entity.Example;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.math.BigDecimal;
import java.util.*;
import java.text.ParseException;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.BeanUtils;
import com.example.onlinemonitoring.Util.LanguageManager;

/**
 * Created by zkw
 * on 2022/4/3.
 * <p>
 * 抽象service实现，实现了基础mapper的基础方法，所有需要基础mapper的service实现类继承这个类
 */
public abstract class CommonAbstractBaseService<T> extends AbstractBaseService<T> {
    @Autowired
    LanguageManager languageManager;
    private Class<T> modelClass;// 当前泛型的真实类型Class

    @SuppressWarnings("unchecked")
    public CommonAbstractBaseService() {
        ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
        modelClass = (Class<T>) pt.getActualTypeArguments()[0];
    }

    public T getModel(T record) {
        return selectOneByExample(ConditionDispose.defaultDisposeByInUse(record, record.getClass()));
    }

    public T getModel(DefaultPropertyByInsert record) {
        return selectOneByExample(ConditionDispose.defaultDisposeByInUse(record, modelClass));
    }

    public int Delete(T record) {
        if (deleteByExample(ConditionDispose.defaultDispose(record, record.getClass())) != 0)
            return 1;
        else
            return 0;
    }

    public int DeleteByClass(DefaultProperty record) {
        if (deleteByExample(ConditionDispose.defaultDispose(record, modelClass)) != 0)
            return 1;
        else
            return 0;
    }

    /**
     * 删除所有
     * 
     * @return
     */
    public int Delete() {
        if (DeleteByClass(new DefaultProperty()) != 0)
            return 1;
        else
            return 0;
    }

    /**
     * 更新实时表
     * 
     * @param record
     * @param byid
     * @return
     */
    public int Update(T record, Boolean byid) {
        if (byid)
            return updateByPrimaryKeySelective(record);
        else
            return updateByExampleSelective(record, ConditionDispose.defaultDisposeByUpdate(record, record.getClass()));
    }

    /**
     * 查询分页
     * 
     * @param record
     * @param qo
     * @return
     */
    public MyResult<T> getList(QueryObject qo, Example example) {
        if (qo.getPage() != null || qo.getLimit() != null) {
            PageHelper.startPage(qo.getPage(), qo.getLimit());
        }
        List<T> list = selectByExample(example);
        MyResult<T> result = new MyResult<T>();
        result.setData(list);
        if (list.size() != 0) {
            result.setCode(0);
            result.setMsg("success");
            if (qo.getPage() != null || qo.getLimit() != null) {
                PageInfo<T> pi = new PageInfo<>(list);
                result.setCount((int) pi.getTotal());
            } else {
                result.setCount(list.size());
            }
        } else {
            result.setCode(1);
            result.setMsg("数据为空");
        }
        return result;
    }

    /**
     * 查询不分页
     * 
     * @param record
     * @return
     */
    public MyResult<T> getList(Example example) {
        List<T> list = selectByExample(example);
        MyResult<T> result = new MyResult<T>();
        result.setData(list);
        if (list.size() != 0) {
            result.setCode(0);
            result.setMsg("success");
            result.setCount(list != null && !list.isEmpty() ? list.size() : 0);
        } else {
            result.setCode(1);
            result.setMsg("数据为空");
        }
        return result;
    }

    /**
     * 查询不分页无条件
     * 
     * @param record
     * @return
     */
    public MyResult<T> getList() {
        List<T> list = selectAll();
        MyResult<T> result = new MyResult<T>();
        result.setData(list);
        if (list.size() != 0) {
            result.setCode(0);
            result.setMsg("success");
            result.setCount(list != null && !list.isEmpty() ? list.size() : 0);
        } else {
            result.setCode(1);
            result.setMsg("数据为空");
        }
        return result;
    }

    /**
     * 
     * @param t
     * @return
     */
    public List<T> selectalarm(T t) {
        return selectByExample(ConditionDispose.defaultDisposeByInUse(t, modelClass));
    }

    /**
     * 获取对应字段的值
     *
     * @param field 字段
     * @param t     对象
     * @param <T>
     * @return
     */
    private static <T> String getValue(String field, T t) {
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(t.getClass());
            PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor descriptor : descriptors) {
                if (descriptor.getName().equals(field)) {
                    if (descriptor.getReadMethod().invoke(t) != null)
                        return descriptor.getReadMethod().invoke(t).toString();
                }
            }
        } catch (IntrospectionException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 实例化T
     * 
     * @param <T>
     * @param clazz
     * @return
     */
    static <T> T newTclass(Class<T> clazz) {
        T obj = null;
        try {
            obj = clazz.getDeclaredConstructor().newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
        return obj;
    }

    /**
     * 导出Excel
     * 
     * @param record
     * @param pageBase
     * @return
     */
    public Workbook writeToExcelByList(List<T> list) {
        List<String> legend = new ArrayList<>();
        List<String> columns = new ArrayList<>();
        Appalarm t = new Appalarm();
        String[] leg = {
                "stationid|1|" + languageManager.getLan().getStationID() + "",
                "devicegroup|1|" + languageManager.getLan().getDeviceGroup() + "",
                "deviceaddr|1|" + languageManager.getLan().getDeviceAddress() + "",
                "deviceid|1|" + languageManager.getLan().getDeviceID() + "",
                "devicename|1|" + languageManager.getLan().getDeviceName() + "",
                "pointaddr|1|" + languageManager.getLan().getPointAddress() + "",
                "pointname|1|" + languageManager.getLan().getPointName() + "",
                "starttime|1|" + languageManager.getLan().getStartTime() + "",
                "endtime|1|" + languageManager.getLan().getEndTime() + "",
                "alarmlevel|1|" + languageManager.getLan().getAlarmLevel() + "",
                "data|1|" + languageManager.getLan().getMeasuredValue() + "",
                "warnvalue|1|" + languageManager.getLan().getWarningValue() + "",
                "warnrelievevalue|1|" + languageManager.getLan().getWarningRelieveValue() + "",
                "alarmvalue|1|" + languageManager.getLan().getAlarmValue() + "",
                "alarmrelievevalue|1|" + languageManager.getLan().getAlarmRelieveValue() + "",
                "alarmmessage|1|" + languageManager.getLan().getAlarmDetails() + "",
                "status|1|" + languageManager.getLan().getAlarmStatus() + "" };

        for (int i = 0; i < leg.length; i++) {
            if (leg[i].split("\\|")[1].equals("1")) {
                String[] ls = leg[i].split("\\|");
                if (getValueType(ls[0], t) || getValueType(ls[0], t)) {
                    legend.add(ls[2]);
                    columns.add(ls[0]);
                }
            }
        }

        // 创建工作薄
        Workbook wb = new XSSFWorkbook();
        // 标题和页码
        CellStyle titleStyle = wb.createCellStyle();
        // 设置单元格对齐方式,水平居左
        titleStyle.setAlignment(HorizontalAlignment.LEFT);
        // 设置字体样式
        Font titleFont = wb.createFont();
        // 字体高度
        titleFont.setFontHeightInPoints((short) 12);
        // 字体样式
        titleFont.setFontName("黑体");
        titleStyle.setFont(titleFont);
        // 创建sheet
        Sheet sheet = wb.createSheet(languageManager.getLan().getHistoricalDetails());
        // 自动设置宽度
        sheet.autoSizeColumn(0);

        // 在sheet中添加标题行// 行数从0开始
        Row row = sheet.createRow((int) 0);
        for (int i = 0; i < legend.size(); i++) {
            if (legend.get(i).equals(languageManager.getLan().getDataTime())) {
                sheet.setColumnWidth(i, 5000);
            }
            Cell cell = row.createCell(i);
            cell.setCellValue(legend.get(i));
            cell.setCellStyle(titleStyle);
        }
        // 数据样式 因为标题和数据样式不同 需要分开设置 不然会覆盖
        CellStyle dataStyle = wb.createCellStyle();
        // 设置居中样式，水平居中
        dataStyle.setAlignment(HorizontalAlignment.CENTER);

        // 数据从序号1开始
        try {
            int index = 1;
            for (T value : list) {
                // 默认的行数从0开始，为了统一格式设置从1开始，就是从excel的第二行开始
                row = sheet.createRow(index);
                index++;
                for (int i = 0; i < columns.size(); i++) {
                    Cell cell = row.createCell(i);
                    // 为当前列赋值
                    String val = getKValue(columns.get(i), value);
                    if (columns.get(i).equals("status")) {
                        switch (val) {
                            case "0":
                                val = languageManager.getLan().getRestored();
                                break;
                            case "1":
                                val = languageManager.getLan().getAlarmActive();
                                break;
                            default:
                                break;
                        }
                    }
                    if (columns.get(i).equals("alarmlevel")) {
                        switch (val) {
                            case "0":
                                val = languageManager.getLan().getNormal();
                                break;
                            case "1":
                                val = languageManager.getLan().getWarning();
                                break;
                            case "2":
                                val = languageManager.getLan().getAlarm();
                                break;
                            default:
                                break;
                        }
                    }
                    cell.setCellValue(val);
                    // 设置数据的样式
                    cell.setCellStyle(dataStyle);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return wb;
    }

    /**
     * 判断字段是否是整数或浮点数
     *
     * @param field 字段
     * @param t     对象
     * @param <T>
     * @return
     */
    private static <T> Boolean getValueType(String field, T t) {
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(t.getClass());
            PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor descriptor : descriptors) {
                if (descriptor.getName().equals(field)) {
                    return Long.class.isAssignableFrom(descriptor.getReadMethod().getReturnType()) ||
                            Integer.class.isAssignableFrom(descriptor.getReadMethod().getReturnType()) ||
                            Short.class.isAssignableFrom(descriptor.getReadMethod().getReturnType()) ||
                            BigDecimal.class.isAssignableFrom(descriptor.getReadMethod().getReturnType()) ||
                            Double.class.isAssignableFrom(descriptor.getReadMethod().getReturnType()) ||
                            Float.class.isAssignableFrom(descriptor.getReadMethod().getReturnType());
                }
            }
        } catch (IntrospectionException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 通过反射获取历史表字段的值
     *
     * @param field 字段
     * @param k     对象
     * @param <K>
     * @return
     */
    protected String getKValue(String field, T k) {
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(k.getClass());
            PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor descriptor : descriptors) {
                if (descriptor.getName().equals(field)) {
                    String retvalue = myCustomName(field,
                            descriptor.getReadMethod().invoke(k) != null
                                    ? descriptor.getReadMethod().invoke(k).toString()
                                    : "");
                    if (retvalue != null && !retvalue.equals("")) {// 自定义的返回值表达形式
                        return retvalue;
                    }
                    if (descriptor.getReadMethod().invoke(k) != null) {
                        if (Date.class.isAssignableFrom(descriptor.getReadMethod().getReturnType())) {// 日期格式化
                            try {
                                return HexUtil.stosdate(descriptor.getReadMethod().invoke(k).toString());
                            } catch (IllegalArgumentException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            } catch (ParseException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                            ;
                        } else {
                            return descriptor.getReadMethod().invoke(k).toString();
                        }
                    }
                }
            }
        } catch (IntrospectionException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }

    protected String myCustomName(String field, String string) {
        return "";
    }
}
